/**
 * 
 */
package com.m7012e.a_remote.ar_stub.old;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;

import com.leoj.utils.CallbackMethod;
import com.leoj.utils.Couple;
import com.leoj.utils.Handler;
import com.leoj.utils.finite_states_machine.Machine;
import com.m7012e.a_remote.ar_listeners.exception.WrongMessageProtocolException;
import com.m7012e.a_remote.ar_stub.old.protocols.RemoteSimpleState;
import com.m7012e.a_remote.commons.ARemoteMulticastSender;
import com.m7012e.a_remote.commons.ARemoteTcpSocket;
import com.m7012e.a_remote.communication.DisplayDiscoveryMessage;
import com.m7012e.a_remote.communication.Message;
import com.m7012e.a_remote.communication.TcpMessage;
import com.m7012e.a_remote.communication.positioning.Position;
import com.m7012e.a_remote.communication.tcpMessages.EvaluatedDistanceMessage;

/**
 * @author leoj
 *
 */
public class ARemoteRemoteMessageAnalyser implements Handler<Message> {

	private Machine<RemoteSimpleState, TcpMessage> _protocol;
	private TcpMessage _lastMsg;
	private ARemoteTcpSocket _tcpConnection;
	
	private Position _currentPosition;
	private String _arAddress;
	private int _arPort;
	
	private Date _waitingLimitTime;
	
	private SortedSet<ARemoteDisplay> _availableDisplay;
	
	public ARemoteRemoteMessageAnalyser(){
		Handler<RemoteSimpleState> actions = new Handler<RemoteSimpleState>() {
			@Override
			public void handle(RemoteSimpleState st) {
				switch (st) {
				case SENDING_DISCOVERY:
					try {
						ARemoteMulticastSender.INSTANCE.sendMessage(new DisplayDiscoveryMessage(_arAddress, _arPort, _currentPosition));
					} catch (IOException e) {
						e.printStackTrace();
					}
					_protocol.handle(null);
					break;
				case WAITING_ANSWERS:
					//TODO do nothing but waiting ...
					break;
				case SELECTING_DISPLAY:
					//sort the map
					boolean connectionSuccess = false;
					Iterator<ARemoteDisplay> ite = _availableDisplay.iterator();
					while(!connectionSuccess && ite.hasNext()){
						InetSocketAddress address = ite.next().getFirst();
						//TODO connect to address
						try {
							
							_tcpConnection.connect(address);
							//TODO send something and wait for the answer
							connectionSuccess = true;
							System.out.println("yeeeaaaaappeeeeeee we are connected to a Daemon !");
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
					if(!connectionSuccess){
						//TODO no connection  ! 
						// do something !
						throw new RuntimeException("woops , no connection was made ... ");
					}
					break;
				case CONTROLING_REMOTE_DISPLAY:
					//TODO success !
					System.out.println("Starting to control the remote display !");
				}
			}
		};
		CallbackMethod<RemoteSimpleState, Couple<RemoteSimpleState, TcpMessage>> transitions = new CallbackMethod<RemoteSimpleState, Couple<RemoteSimpleState,TcpMessage>>() {
			@Override
			public RemoteSimpleState handle(Couple<RemoteSimpleState, TcpMessage> args) {
				RemoteSimpleState state = args.getFirst();
				TcpMessage msg = args.getSecond();
				
				switch (state) {
				case SENDING_DISCOVERY:
					if(msg == null){
						//ok forced transition 
						_waitingLimitTime = new Date(Calendar.getInstance().getTimeInMillis()+5000);
						return RemoteSimpleState.WAITING_ANSWERS;
					}else{
						// not supposed to happen !
						throw new WrongMessageProtocolException();
					} 
//					break;
				case WAITING_ANSWERS:
					if (msg instanceof EvaluatedDistanceMessage) {
						EvaluatedDistanceMessage distMsg = (EvaluatedDistanceMessage) msg;
						_availableDisplay.add(new ARemoteDisplay(new InetSocketAddress(distMsg.address, distMsg.port), distMsg.distance));
						if(_waitingLimitTime.before(new Date())){
							//limit passed
							return RemoteSimpleState.SELECTING_DISPLAY;
						}else{
							return RemoteSimpleState.WAITING_ANSWERS;
						}
					}else{
						throw new WrongMessageProtocolException();
					}
				case SELECTING_DISPLAY:
					
				default:
					break;
				}
				return null;
			}
		};
	}
	
	/* (non-Javadoc)
	 * @see com.leoj.utils.Handler#handle(java.lang.Object)
	 */
	@Override
	public void handle(Message args) {
		// TODO Auto-generated method stub

	}

}
